package com.ys.entity.base;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.ContextLoader;

import com.bo.util.MapUtil;
import com.ys.mapper.business.CommonMapper;

import tk.mybatis.mapper.util.StringUtil;

public abstract class BaseEntity<E extends BaseEntity<E>> {
	
	public static ApplicationContext ac;

	public CommonMapper dao;
	
	public String field;
	
	private List<String> fields = new ArrayList<String>();
	
	private List<String> diyConfs= new ArrayList<String>();
	
	private List<String> outerJoins= new ArrayList<String>();
	
	private List<String> innerJoins= new ArrayList<String>();
	
	public String groupBy;
	
	public E queryFirst() {
		
		this.size = 1;
		this.page = 0;
		
		List<E> list = queryList();
		if (list != null && list.size() > 0) {
			return list.get(0);
		}
		return null;
	};
	
	public Map<String, Object> queryFirstMap() {
		
		this.size = 1;
		this.page = 0;
		
		List<Map<String, Object>> list = queryMap();
		if (list != null && list.size() > 0) {
			return list.get(0);
		}
		return null;
	};
	
	@SuppressWarnings("unchecked")
	public List<E> queryList() {
		E entity = (E) this;
		
		if (ac == null) {
			ac = ContextLoader.getCurrentWebApplicationContext();
		}

		if (dao == null) {
			dao = (CommonMapper) ac.getBean("commonMapper");
		}
		
		try {
			List<Map<String, Object>> listMap;
			
			listMap = dao.searchMap(generateSearchSql());
			
			List<E> listEntity = new ArrayList<E>();
			for(Map<String, Object> map : listMap) {
				E activity = (E) MapUtil.mapToObject(map, entity.getClass());
				listEntity.add(activity);
			}
			return listEntity;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	};
	
	public List<Map<String, Object>> queryMap() {
		
		if (ac == null) {
			ac = ContextLoader.getCurrentWebApplicationContext();
		}

		if (dao == null) {
			dao = (CommonMapper) ac.getBean("commonMapper");
		}
		
		try {

			return dao.searchMap(generateSearchSql());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return null;
	};
	
	public int count() {
		
		if (ac == null) {
			ac = ContextLoader.getCurrentWebApplicationContext();
		}

		if (dao == null) {
			dao = (CommonMapper) ac.getBean("commonMapper");
		}
		return dao.countInteger(generateCountSql());

	};
	
	public BigDecimal sumDecimal() {
		
		if (ac == null) {
			ac = ContextLoader.getCurrentWebApplicationContext();
		}

		if (dao == null) {
			dao = (CommonMapper) ac.getBean("commonMapper");
		}
		
		return dao.sumBigDecimal(generateSumSql());

	};
	
	/**
	 * 添加字段
	 * @param field 格式如A.merchant_id AS merchantId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E addField(String field) {
		this.fields.add(field);
		return (E) this;
	}
	
	/**
	 * 左连接语句，示例：t_merchant B ON A.merchant_id = B.id
	 * @param sql
	 */
	@SuppressWarnings("unchecked")
	public E addLeftJoin(String sql) {
		this.outerJoins.add("LEFT JOIN " + sql + " ");
		return (E) this;
	}
	
	/**
	 * 右连接语句，示例：t_merchant B ON A.merchant_id = B.id
	 * @param sql
	 */
	@SuppressWarnings("unchecked")
	public E addRightJoin(String sql) {
		this.outerJoins.add("RIGHT JOIN " + sql + " ");
		return (E) this;
	}
	
	/**
	 * 清除连接语句，一般用于统计
	 * @param sql
	 */
	@SuppressWarnings("unchecked")
	public E clearLeftJoin() {
		this.outerJoins = new ArrayList<String>();
		return (E) this;
	}
	
	/**
	 * 内连接语句，示例：merchant_account_running B ON B.merchant_id = A.merchant_id
	 * @param sql
	 */
	@SuppressWarnings("unchecked")
	public E addInnerJoin(String sql) {
		this.innerJoins.add("INNER JOIN " + sql + " ");
		return (E) this;
	}
	
	public String generateField() {
		if (field != null) {
			return this.field;
		}
		
		StringBuffer sb = new StringBuffer("");
		
		// 拼接field
		Field[] fieldArr = this.getClass().getDeclaredFields();
		for (Field field : fieldArr) {
			String name = field.getName();
			sb.append("A.`" + StringUtil.camelhumpToUnderline(name) + "` AS `" + name + "`,");
		}
		
		for (String str : fields) {
			sb.append(str + ",");
		}
		
		
		String fileds = sb.toString();
		int length = fileds.length();
		this.field = fileds.substring(0, length - 1);
		return this.field;
	}
	
	/**
	 * 设置字段
	 * @param fields，格式：ifnull(sum(A.detail_real_price,0))，或者A.merchant_id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E setField(String fields) {
		this.field = fields;
		return (E) this;
	}
	
	/**
	 * 添加条件
	 * @param condition 格式：A.merchant_id=1
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E where(String condition) {
		this.diyConfs.add("and " + condition);
		return (E) this;
	}
	
	/**
	 * 添加条件
	 * @param field 格式：A.merchant_id
	 * @param intVal 格式：1
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E where(String field, Integer intVal) {
		this.diyConfs.add("and " + field + "=" + intVal + " ");
		return (E) this;
	}
	
	/**
	 * 添加条件
	 * @param field 格式：A.merchant_id
	 * @param longVal 格式：1
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E where(String field, Long longVal) {
		this.diyConfs.add("and " + field + "=" + longVal + " ");
		return (E) this;
	}
	
	/**
	 * 添加条件
	 * @param field 格式：A.merchant_id
	 * @param strVal 格式：xxxxxx
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E where(String field, String strVal) {
		this.diyConfs.add("and " + field + "='" + strVal + "' ");
		return (E) this;
	}
	
	/**
	 * 生成表名
	 * @return
	 */
	public String generateTableAllName() {
		return this.getClass().getAnnotation(javax.persistence.Table.class).name();
	}
	
	/**
	 * 生成主键名
	 * @return
	 */
	public String generatePrimaryKeyName() {
		return this.getClass().getAnnotation(javax.persistence.Table.class).catalog();
	}
	
	/**
	 * 生成完整的sql语句（搜索）
	 * @return
	 */
	public String generateSearchSql() {
		StringBuffer sb = new StringBuffer("select").append(" ")
		.append(generateField()).append(" ")
		.append("from").append(" ")
		.append(generateTableAllName()).append(" A ");

		// 拼接自定义搜索
		for (String sql : this.outerJoins) {
			sb.append(sql + " ");
		}

		// 拼接自定义搜索
		for (String sql : this.innerJoins) {
			sb.append(sql + " ");
		}
		
		sb.append(generateCondition()).append(" ").append(generateGroupby()).append(" ").append(generateOrderBy());

//		logger.info(sb.toString());
		
		return sb.toString();
	}
	
	/**
	 * 生成条件语句，从where到order by之间
	 * @return
	 */
	public String generateCondition() {
		
		StringBuffer sb = new StringBuffer("");
		
		sb.append("WHERE 1=1 ");
		
		Class<?> clazz = this.getClass();
		for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				String name = field.getName();
				if (
						"orderby".equals(name)
						|| "sorttype".equals(name)
						|| "size".equals(name)
						|| "page".equals(name)
						|| "isCount".equals(name)
						
						|| "diyConfs".equals(name)
						|| "outerJoins".equals(name)
						|| "innerJoins".equals(name)
						|| "e".equals(name)
						|| "logger".equals(name)
//						|| "sqlSession".equals(name)
						|| "field".equals(name)
						|| "fields".equals(name)
						|| "groupBy".equals(name)
						|| "ac".equals(name)
						|| "dao".equals(name)
						|| "daoSys".equals(name)
						) {
					continue;
				}
				if (!field.isAccessible()) {
					field.setAccessible(true);
				}
				try {
					Object value = field.get(this);
					if (value != null && !"".equals(value)) {
						sb.append("AND A." + StringUtil.camelhumpToUnderline(name) + " = '" + value + "' ");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		
		
		// 拼接自定义搜索
		for (String sql : this.diyConfs) {
			sb.append(sql + " ");
		}
		
		return sb.toString().replace("#", "").replace("{", "").replace("}", "");
	}
	
	/**
	 * 生成 group by 语句
	 * @return
	 */
	public String generateGroupby() {
		StringBuffer sb = new StringBuffer();
		if (groupBy != null && groupBy.length() > 0) {
			sb.append("group by " + groupBy + " ");
		}
		return sb.toString();
	}
	
	/**
	 * 生成 order by 语句
	 * @return
	 */
	public String generateOrderBy() {
		StringBuffer sb = new StringBuffer();
		if (orderby != null && orderby.length() > 0) {
			if (orderby.contains(".")) {
				sb.append("order by " + orderby + " ");
			} else if (preOrderby != null) {
				sb.append("order by " + preOrderby + orderby + " ");
			} else {
				sb.append("order by A." + orderby + " ");
			}
		} else {
			sb.append("order by A." + generatePrimaryKeyName() + " ");
		}
		
		if (sorttype != null && sorttype.length() > 0) {
			sb.append(sorttype + " ");
		}
		
		if (size != null && page != null) {
			sb.append("limit " + page + "," + size + "");
		}
		return sb.toString();
	}
	
	/**
	 * 生成完整的sql语句（统计）
	 * @return
	 */
	public String generateCountSql() {
		StringBuffer sb = new StringBuffer("select count(1)").append(" ")
		.append("from").append(" ")
		.append(generateTableAllName()).append(" A ");

		// 拼接自定义搜索
		for (String sql : this.outerJoins) {
			sb.append(sql + " ");
		}

		// 拼接自定义搜索
		for (String sql : this.innerJoins) {
			sb.append(sql + " ");
		}
		
//		sb.append(generateCondition()).append(" ").append(generateGroupby());
		sb.append(generateCondition()).append(" ");
		
		return sb.toString();
	}
	
	/**
	 * 生成完整的sql语句（求和）
	 * @return
	 */
	public String generateSumSql() {
		StringBuffer sb = new StringBuffer("select ").append(this.field).append(" ")
				.append("from").append(" ")
				.append(generateTableAllName()).append(" A ");

		// 拼接自定义搜索
		for (String sql : this.outerJoins) {
			sb.append(sql + " ");
		}

		// 拼接自定义搜索
		for (String sql : this.innerJoins) {
			sb.append(sql + " ");
		}
		
//		sb.append(generateCondition()).append(" ").append(generateGroupby());
		sb.append(generateCondition()).append(" ");
		
		return sb.toString();
	}
	
	
	public Integer size; // 分页用-每页条数
	public Integer page; // 分页用-起始数
	public String orderby; // 排序用-排序字段，值可以是驼峰，也可以是原数据库字段
	public String sorttype; // 排序用-排序方式
	private String preOrderby; // orderby字段的前缀
	
	public boolean isCount; // 统计用
	@SuppressWarnings("unchecked")
	public E setSize(Integer limit) {
		this.size = limit;
		return (E) this;
	}
	@SuppressWarnings("unchecked")
	public E setPage(Integer start) {
		this.page = start;
		return (E) this;
	}
	@SuppressWarnings("unchecked")
	public E setOrderby(String orderby) {
		this.orderby = orderby;
		return (E) this;
	}
	@SuppressWarnings("unchecked")
	public E setPreOrderby(String preOrderby) {
		this.preOrderby = preOrderby;
		return (E) this;
	}
	@SuppressWarnings("unchecked")
	public E setSorttype(String sorttype) {
		this.sorttype = sorttype == null ? "desc" : sorttype;
		return (E) this;
	}
	@SuppressWarnings("unchecked")
	public E setIsCount(String isCount) {
		if (isCount != null && "on".equals(isCount)) {
			this.isCount = true;
		}
		return (E) this;
	}
	/**
	 * 设置group by
	 * @param groupBy格式：A.merchant_id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public E setGroupby(String groupBy) {
		this.groupBy = groupBy;
		return (E) this;
	}
}